﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Windows;

namespace WpfWordsLearner
{
	public static class Extension
	{
		public static Queue<T> ToQueue<T>(this IEnumerable<T> enumerable) where T : class
		{
			if (enumerable == null)
				return null;

			Queue<T> que = new Queue<T>();
			foreach (T item in enumerable)
			{
				que.Enqueue(item);
			}

			return que;
		}

		// Helper to search up the VisualTree
		public static T FindAnchestor<T>(this DependencyObject current)
			where T : DependencyObject
		{
			do
			{
				if (current is T)
				{
					return (T)current;
				}
				current = System.Windows.Media.VisualTreeHelper.GetParent(current);
			}
			while (current != null);
			return null;
		}

		public static UIElement GetDragElementFromHitTest(this UIElement dragSourceContainer, System.Windows.Input.MouseEventArgs args)
		{
			System.Windows.Media.HitTestResult hr = System.Windows.Media.VisualTreeHelper.HitTest(dragSourceContainer,
															args.GetPosition((IInputElement)dragSourceContainer));
			return hr.VisualHit as UIElement;
		}

		/// <summary>
		/// A simple iterator method to expose the visual tree to LINQ (parent to child).
		/// </summary>
		/// <param name="start">Starting root</param>
		/// <param name="predicate">Predicate called for each item to provide filter (can be null)</param>
		/// <returns>Enumerable list of visuals</returns>
		public static IEnumerable<T> EnumerateVisualTree<T>(this DependencyObject start, Predicate<T> predicate) where T : DependencyObject
		{
			for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(start); i++)
			{
				var rawChild = System.Windows.Media.VisualTreeHelper.GetChild(start, i);
				var child = rawChild as T;
				if (child != null && (predicate == null || predicate(child)))
				{
					yield return child;
					foreach (var childOfChild in EnumerateVisualTree(child, predicate))
						yield return childOfChild;
				}
				else if (child == null)
				{
					foreach (var childOfChild in EnumerateVisualTree(rawChild, predicate))
						yield return childOfChild;
				}
			}
		}

		/// <summary>
		/// A simple iterator method to expose the visual tree to LINQ going backwards (child to parent)
		/// </summary>
		/// <param name="start">Starting child</param>
		/// <param name="predicate">Predicate called for each item to provide filter (can be null)</param>
		/// <returns>Enumerable list of visuals</returns>
		public static IEnumerable<T> ReverseEnumerateVisualTree<T>(this DependencyObject start, Predicate<T> predicate) where T : DependencyObject
		{
			for (; ; )
			{
				var parent = System.Windows.Media.VisualTreeHelper.GetParent(start);
				if (parent == null)
					break;
				var tParent = parent as T;
				if ((predicate == null || predicate(tParent)))
					yield return tParent;
				start = parent;
			}
		}
	}


	/// <summary>
	/// Properties used to control the design surface details
	/// </summary>
	public static class Designer
	{
		/// <summary>
		/// Returns true/false whether the code is currently being executed by a designer surface
		/// (Blend or Visual Studio).
		/// </summary>
		public static bool InDesignMode
		{
			get
			{
				return ((bool)(System.ComponentModel.DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue));
			}
		}
	}
}
